/*
 * Created on 2005-7-17
 *
 */
package bma.common.langutil.bean;

import java.util.LinkedList;
import java.util.List;

import bma.common.langutil.convert.ConvertManager;
import bma.common.langutil.core.ExceptionUtil;
import bma.common.langutil.core.StringUtil;

/**
 * 
 * @author guanzhong
 * @since 1.0 (imported from BMA.ESP Project)
 * 
 */
public class BeanUtil {

	public static boolean isValueClass(ConvertManager cm, Class type) {
		try {
			return cm.canCast(String.class, type);
		} catch (Exception e) {
			throw ExceptionUtil.throwRuntime(e);
		}
	}

	public static boolean isWritable(BeanObjectProperty prop) {
		if (prop == null)
			return false;
		return prop.accessible(AccessType.SET);
	}

	public static boolean isReadable(BeanObjectProperty prop) {
		if (prop == null)
			return false;
		return prop.accessible(AccessType.GET);
	}

	public static boolean hasNext(Class type) {
		if (type == null)
			return false;
		return type != Object.class;
	}

	public static Class next(Class type) {
		Class stype = type.getSuperclass();
		if (stype == null || stype == Object.class)
			return null;
		return stype;
	}

	public static List<BeanObjectProperty> getProperties(BeanSystem sys,
			Class type) {
		List<BeanObjectProperty> result = new LinkedList<BeanObjectProperty>();
		getProperties(sys, type, result);
		return result;
	}

	public static void getProperties(BeanSystem sys, Class type,
			List<BeanObjectProperty> result) {
		BeanClass bean = sys.getBeanClass(type);
		getProperties(bean, result, false);
	}

	public static void getProperties(BeanClass bean,
			List<BeanObjectProperty> result, boolean skipSame) {
		if (bean == null)
			return;
		if (bean instanceof BeanObject) {
			BeanObject bo = (BeanObject) bean;
			List<BeanObjectProperty> list = bo.getProperties();
			if (skipSame && result.size() > 0) {
				BeanObjectProperty[] tmp = result
						.toArray(new BeanObjectProperty[result.size()]);
				for (BeanObjectProperty p : list) {
					boolean s = false;
					for (int i = 0; i < tmp.length; i++) {
						if (StringUtil.equals(p.getName(), tmp[i].getName())) {
							s = true;
							break;
						}
					}
					if (!s) {
						result.add(p);
					}
				}
			} else {
				result.addAll(list);
			}
		}
		return;
	}

	public static void listProperties(BeanSystem sys, Class cls,
			List<BeanObjectProperty> result) {
		if (cls == null)
			return;
		BeanClass bean = sys.getBeanClass(cls);
		getProperties(bean, result, true);
		Class parent = next(cls);
		if (parent != null) {
			listProperties(sys, parent, result);
		}
	}

	public static BeanObjectProperty getProperty(BeanSystem sys, Class cls,
			String name) {
		BeanClass bcls = sys.getBeanClass(cls);
		return getProperty(sys, bcls, name);
	}

	public static BeanObjectProperty getProperty(BeanSystem sys,
			BeanClass bcls, String name) {
		if (bcls == null)
			return null;
		if (bcls instanceof BeanObject) {
			BeanObject bo = (BeanObject) bcls;
			BeanObjectProperty prop = bo.getDeclaredProperty(name);
			if (prop != null)
				return prop;
		}
		Class sp = bcls.getPrototype().getSuperclass();
		if (sp != null && sp != Object.class) {
			return getProperty(sys, sp, name);
		}
		return null;
	}
}
